package limits

import (
	"gitee.com/wumeisifu/gobag/limiter"
	"sync"
)

type bizRateLimits struct {
	bizLimitSetMapLock    *sync.Mutex
	bizLimitSetMap        map[interface{}]*limiter.GBRateLimitSet
}

// 根据业务取得对应对象
func (obj *bizRateLimits) businessTarget(bizName interface{}) * limiter.GBRateLimitSet {
	// 加访问锁
	obj.bizLimitSetMapLock.Lock()
	defer obj.bizLimitSetMapLock.Unlock()
	// 查找对象
	v, ok := obj.bizLimitSetMap[bizName]
	// 存在直接返回
	if ok {
		return v
	}
	// 创建新对象，暂不允许自定义检测周期
	v = limiter.GBNewRateLimitSet(bizName, 180)
	// 保存对象
	obj.bizLimitSetMap[bizName] = v
	// 创建成功
	return v
}

var (
	bizRateLimitsObj     *bizRateLimits
	bizRateLimitsObjOnce sync.Once
)

// 初始化唯一实例
func onceInitRateLimitsInstance() {
	bizRateLimitsObj = &bizRateLimits{
		bizLimitSetMapLock: &sync.Mutex{},
		bizLimitSetMap:     make(map[interface{}]*limiter.GBRateLimitSet, 0),
	}
}

// 获取唯一实例
func instanceOfRateLimits() * bizRateLimits {
	bizRateLimitsObjOnce.Do(onceInitRateLimitsInstance)
	return bizRateLimitsObj
}

// 取得某业务下某 key 当前周期剩余额度
//
// @param bizName 业务
// @param key 目标
// @param intervals 周期间隔（秒数）
// @param limit 每周期最大额度
//
// @return 剩余额度数量，可能是负数
//
func GBRateLimBizGetLeft(bizName, key interface{}, intervals, limit int) int {
	// 取得目标业务对象
	bizTarget := instanceOfRateLimits().businessTarget(bizName)
	// 转发
	return bizTarget.GetLeft(key, intervals, limit)
}

// 某业务下某 key 周期性速率限制检测，是否被限制
//
// @param bizName 业务
// @param key 目标
// @param intervals 周期间隔（秒数）
// @param limit 每周期最大额度
//
// @return true：被限制，false：未被限制
//
func GBRateLimBizIsLimited(bizName, key interface{}, intervals, limit int) bool {
	// 取得目标业务对象
	bizTarget := instanceOfRateLimits().businessTarget(bizName)
	// 转发
	return bizTarget.IsLimited(key, intervals, limit)
}

// 某业务下某 key 周期性速率限制检测
//
// @param bizName 业务
// @param key 目标
// @param intervals 周期间隔（秒数）
// @param limit 每周期最大额度
// @param consume 本次消费额度，可以传"0"表示不消费
//
// @return true：被限制，false：未被限制，当实际消费额度大于"0"时，一定会返回"false"
// @return 本次实际消费额度
// @return 本周期剩余额度
//
func GBRateLimBizCheckLimit(bizName, key interface{}, intervals, limit, consume int) (bool, int, int) {
	// 取得目标业务对象
	bizTarget := instanceOfRateLimits().businessTarget(bizName)
	// 转发
	return bizTarget.CheckLimit(key, intervals, limit, consume)
}


// 某业务下某 key 周期性速率限制检测，是否被限制
//
// @param bizName 业务
// @param key 目标
// @param intervals 周期间隔（秒数）
// @param limit 每周期最大额度
// @param consume 本次消费额度，可以传"0"表示不消费
//
// @return true：被限制，false：未被限制，当实际消费额度大于"0"时，一定会返回"false"
//
func GBRateLimBizCheckIsLimited(bizName, key interface{}, intervals, limit, consume int) bool {
	// 取得目标业务对象
	bizTarget := instanceOfRateLimits().businessTarget(bizName)
	// 转发
	return bizTarget.CheckIsLimited(key, intervals, limit, consume)
}
